#include "TianwangFile.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <zlib.h>               // notice this : zlib1g-dev
#include <time.h>
#include <sys/types.h>
using namespace std;

int
TianwangFile::Store(ofstream& outfile,const Url& crUrl, const Page& crPage)
{
    uLong originalLen=crPage.GetContentLength();
    uLong destLen=originalLen*3+12;

    char * pDest=new char[destLen];
    memset(pDest,0,destLen);
    int err=compress((Byte *)pDest,&destLen,(Byte *)(crPage.GetContent().c_str()),originalLen);
    if (err != Z_OK){
        if (err == Z_MEM_ERROR){
            cout<<"Compress: Not enough memory!"<<endl;
        }
        else if (err == Z_BUF_ERROR){
            cout<<"Compress: Not enough memory in the output buffer!"<<endl;
        }
        cout<<"zlib compress errcode:"<<err<<endl;
        delete pDest;
        return -1;
    }

    outfile<<"version: 1.0"<<endl;
    outfile<<"url: "<<crUrl.mOrginUrl<<endl;

    char buf[128];
    memset(buf,0,128);
    time_t  timev;
    time(&timev);
    strftime(buf, 128, "time: %a, %d %b %Y %H:%M:%S GMT", gmtime(&timev));
    outfile<<buf<<endl;

    outfile<<"ip: "<<crUrl.mIP<<endl;
    outfile<<"unzip-length: "<<crPage.GetContentLength()<<endl;

    outfile << "length: "<<destLen<<endl<<endl;
    outfile.write(pDest,destLen);
    outfile << endl;

    delete pDest;
    return 0;
}


int
TianwangFile::Read(ifstream& infile,Page& crPage)
{
    string strLine;
    while (getline(infile, strLine))
    {
        if (strLine.substr(0, 12) == "version: 1.0") {
            if(!getline(infile, strLine))
                break;

            /// get url
            if (strLine.substr(0, 4) == "url:" && strLine.length() > 5){
                string strUrl = strLine.substr(5);
                crPage.SetOrginUrl(strUrl);
            } else {
                continue;
            }
            /// get time
            if(!getline(infile, strLine))
                break;

            /// get ip
            if(!getline(infile, strLine))
                break;

            /// get zip-length
            if(!getline(infile, strLine))
                break;
            int unzipLen=0;
            int len=0;
            if (strLine.substr(0, 14) == "unzip-length: "){
                sscanf(strLine.substr(14).c_str(), "%d", &(unzipLen));
                //                 break;
            }

            if(!getline(infile, strLine))
                break;

            if (strLine.substr(0, 8) == "length: "){
                sscanf(strLine.substr(7).c_str(), "%d", &(len));
            }

            //read a empty line
            getline(infile, strLine);

            char *pFrom=new char[len+1];
            char *pDest=new char[unzipLen+2];
            memset(pFrom,0,len+1);
            memset(pDest,0,unzipLen+2);
            uLong originalLen=unzipLen+1;

            infile.read(pFrom,len);

            int err=uncompress((Byte *)pDest,&originalLen,(Byte *)pFrom,len);
            if (err != Z_OK){
                if (err == Z_MEM_ERROR){
                    cerr << "Uncompress: Not enough memory!" << endl;
                } else if (err == Z_BUF_ERROR){
                    cerr << "Uncompress: Not enough memory in the output buffer!" << endl;
                }
                cerr << "UnCompress: error! errcode:" << err << endl;
                delete pFrom;
                delete pDest;
                return -1;
            }
            crPage.SetContent(string(pDest));
            delete pFrom;
            delete pDest;

            return 0;
        }
    }
    return -1;
}

int
TianwangFile::Test(string fromStr)
{

    uLong originalLen=fromStr.size();
    uLong destLen=originalLen*3+12;
    char * pDest=new char[destLen];
    memset(pDest,0,destLen);
    int err=compress((Byte *)pDest,&destLen,(Byte *)(fromStr.c_str()),originalLen);
    if (err != Z_OK){
        if (err == Z_MEM_ERROR){
            cout<<"Compress: Not enough memory!"<<endl;
        }
        else if (err == Z_BUF_ERROR){
            cout<<"Compress: Not enough memory in the output buffer!"<<endl;
        }
        cout<<"Compress: error! errcode:"<<err<<endl;
        return -1;
    }

    originalLen=destLen*5 + 12;
    char * pOriginal=new char[originalLen];
    memset(pOriginal,0,originalLen);
    err=uncompress((Byte *)pOriginal,&originalLen,(Byte *)pDest,destLen);
    if (err != Z_OK){
        if (err == Z_MEM_ERROR){
            cout<<"Uncompress: Not enough memory!"<<endl;
        }
        else if (err == Z_BUF_ERROR){
            cout<<"Uncompress: Not enough memory in the output buffer!"<<endl;
        }
        cout<<"UnCompress: error! errcode:"<<err<<endl;
        return -1;
    }
    string destStr=string(pOriginal);
    cout<<destStr<<endl;


    return 0;
}
